/*
 * metermon.c
 * Main function of the metermon application.
 *   Usage:  metermond [-d]
 * The application monitors digital inputs on an attached velleman k8085
 * input output card.  It increments a counter on a negative going edge.
 * it updates the log of meter readings at a specified interval.
 * The application responds to two signals:
 *   SIGUSR1 - Reinitialises the meters from the databases.
 *   SIGUSR2 - Forces the current data to be stored in the database.
 *
 * HIST:
 *     05feb2006  GJ  ORIGINAL VERSION
 *     02mar2006  GJ  Added support for signals.
 *     21mar2008  GJ  Changed dates to SQL Date type rather than integer
 *                    and added id column to readings table.
 *     26mar2008  GJ  Updated to make it a nice daemon process - fork and exit
 *                    and use syslog.
 *     13apr2008  GJ  Added command line parameter to allow it to run as 
 *                    daemon or a standard process.
 *
 */

#include "meter.h"
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>

void quit();
void reload();
void sigsave();
int daemon_init();

/* Initialise global variables */
int n_meter;
meterinfo meters[MAXMETER];
ueib_handle *uh;
int daemonf = 0;

int main(int argv, char *argc[]) {
  int i;
  struct tm *tms;
  
  for (i=0;i<argv;i++)
    printf("argc[%d]=%s\n",i,argc[i]);

  if (argv>1) {
    if (!strcmp(argc[1],"-d")) {
      daemonf=1;
    }
  }
  if (!daemonf) 
      printf("metermond starting in terminal mode\n");
    else
      syslog(LOG_INFO, "metermond starting in daemon mode");
  
  if (daemonf) {
    if (daemon_init()<0) {
      fprintf(stderr,"error deamonising myself!!!\n");
      exit(-1);
    }
  }  
  openlog("metermond", LOG_PID, LOG_USER);
  syslog(LOG_INFO,"metermond started");

  /***************************************************
   * Catch SIGINT signals to make sure that we
   * save the current reading to the database on exit
   ****************************************************/
  signal(SIGINT, quit);
  signal(SIGTERM, quit);
  signal(SIGKILL, quit);

  /***************************************************
   * Catch USR1 signals (Signal Number 10) and reload
   * the meter configuration from the database on 
   * receipt of the signal
   ***************************************************/
  signal(SIGUSR1, reload);

  /*****************************************************
   * Catch USR2 signals and save the current data to the 
   * database on receipt of the signal                  
   *****************************************************/
  signal(SIGUSR2, sigsave);

  n_meter = db_initialise_meters();
  syslog(LOG_INFO, "metermon: returned from db_initialise_meters() - n_meter=%d\n",
	 n_meter);
  if (!daemonf)
    printf("metermon: returned from db_initialise_meters() - n_meter=%d\n",
         n_meter);
  syslog(LOG_INFO, "main() Summary\n");
  for (i=0;i<n_meter;i++)
    {
      syslog(LOG_INFO, "Meter Number %d\n",i);
      syslog(LOG_INFO, "   id          =%d\n",meters[i].id);
      syslog(LOG_INFO, "   description =%s\n",meters[i].description);
      syslog(LOG_INFO, "   input       =%d\n",meters[i].input);
      syslog(LOG_INFO, "   reading     =%lf\n",meters[i].reading);
      syslog(LOG_INFO, "   cfac        =%lf\n",meters[i].cfac);
      syslog(LOG_INFO, "   output per. =%d sec\n",meters[i].output_period);
      if (!daemonf) {
        printf("Meter Number %d\n",i);
        printf("   id          =%d\n",meters[i].id);
        printf("   description =%s\n",meters[i].description);
        printf("   input       =%d\n",meters[i].input);
        printf("   reading     =%lf\n",meters[i].reading);
        printf("   cfac        =%lf\n",meters[i].cfac); 
        printf("   output per. =%d sec\n",meters[i].output_period); 
      }
    }


  open_iocard(0);

  while(1) {
    poll_meters();

    time_t tnow = time(NULL);
    tms = localtime(&tnow);
    for (i=0;i<n_meter;i++) {
      if ( tnow > (meters[i].last_output + meters[i].output_period)) {
	syslog(LOG_INFO, "%02d:%02d - Meter %d data (%s) - reading = %10.3lf %s\n",
	       tms->tm_hour, 
	       tms->tm_min, 
	       i,meters[i].description,
	       meters[i].reading,
	       meters[i].unit);
	if(!daemonf) printf("%02d:%02d - Meter %d data (%s) - reading = %10.3lf %s\n",
	       tms->tm_hour, 
	       tms->tm_min, 
	       i,meters[i].description,
	       meters[i].reading,
	       meters[i].unit);
	meters[i].last_output = tnow;
	db_write_data(i);
      }
    }
    sleep(0.1);
  }
  close_iocard();
}


/*
 * save data to database and exit 
 *
 * 19feb2006  GJ  ORIGINAL VERSION
 */
void quit() {
  int i;
  syslog(LOG_INFO, "quit() -exiting\n");
  if (!daemonf) printf("quit() -exiting\n");
  for(i=0;i<n_meter;i++)
    db_write_data(i);

  exit(0);

}


/*****************************************
 * reload the meter configuration from 
 * the database                          
 * 19feb2006  GJ  ORIGINAL VERSION
 */
void reload() {
  int i;
  signal(SIGUSR1, reload);
  n_meter = 0;
  n_meter = db_initialise_meters();
  syslog(LOG_INFO, "reload: returned from db_initialise_meters() - n_meter=%d\n",
	 n_meter);
  syslog(LOG_INFO, "reload() Summary\n");
  for (i=0;i<n_meter;i++)
    {
      syslog(LOG_INFO, "Meter Number %d\n",i);
      syslog(LOG_INFO, "\t%s\n",meters[i].description);
      syslog(LOG_INFO, "\tinput=%d\n",meters[i].input);
      syslog(LOG_INFO, "\treading=%lf\n",meters[i].reading);
      syslog(LOG_INFO, "\tcfac=%lf\n",meters[i].cfac);
      syslog(LOG_INFO, "\n");
    }
  if (!daemonf) {
    printf("reload: returned from db_initialise_meters() - n_meter=%d\n",
	   n_meter);
    printf("reload() Summary\n");
    for (i=0;i<n_meter;i++)
      {
	printf("Meter Number %d\n",i);
	printf("\t%s\n",meters[i].description);
	printf("\tinput=%d\n",meters[i].input);
	printf("\treading=%lf\n",meters[i].reading);
	printf("\tcfac=%lf\n",meters[i].cfac);
	printf("\n");
      }
  }
}
 
/*********************************************
 * Save the current meter readings to the
 * database
 * 02mar2006   GJ   ORIGINAL VERSION
 */
void sigsave() {
  int i;
  syslog(LOG_INFO, "sigsave: saving current data to the database \n");
  if(!daemonf) printf("sigsave: saving current data to the database \n");
  signal(SIGUSR2, sigsave);
  for (i=0;i<n_meter;i++) {
    db_write_data(i);
  }
   
}
 
 
/*********************************************
 * daemon_init:  fork and exit.
 * 26mar2008   GJ   ORIGINAL VERSION
 */
int daemon_init() {
  pid_t pid;
   
  if ( ( pid = fork() ) < 0) 
    return(-1);  /* something's wrong if fork gives an error */
  else if (pid != 0)
    exit(0);  /* parent exits */
   
  /* child continues */
  setsid();   /* become session leader */
  /*chdir("/home/disk2/servers/metermon/cgi-bin/");*/
  umask(0);
  return(0);
}
 
